package com.peking.donations.base.util;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import org.dom4j.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Writer;
import java.util.*;

/**
 * 利用XStream执行Object、Json和XML之间的转换
 * 
 * @author hawk
 *
 */
public class XMLUtil {
    private static Logger logger = LoggerFactory.getLogger(XMLUtil.class);

    @SuppressWarnings("unchecked")
    public static Map<String, Object> fromXml(String xml) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Document doc = DocumentHelper.parseText(xml);
            map = (Map<String, Object>) xml2map(doc.getRootElement());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    public static Map<String, String> fromXmlString(String xml) {
        Map<String, String> map = new HashMap<>();
        try {
            Document doc = DocumentHelper.parseText(xml);
            map = (Map<String, String>) xml2map(doc.getRootElement());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    public static String toXML(Map<String, String> m) {
        XStream xstream = new XStream(new XppDriver() {
            public HierarchicalStreamWriter createWriter(Writer out) {
                return new PrettyPrintWriter(out) {
                    // 对所有xml节点的转换都增加CDATA标记
                    boolean cdata = true;

                    @SuppressWarnings("rawtypes")
                    public void startNode(String name, Class clazz) {
                        super.startNode(name, clazz);
                    }

                    protected void writeText(QuickWriter writer, String text) {
                        if (cdata) {
                            writer.write("<![CDATA[");
                            writer.write(text);
                            writer.write("]]>");
                        } else {
                            writer.write(text);
                        }
                    }
                };
            }
        });
        String s = xstream.toXML(m);
        logger.debug(s);
        return s;
    }

    private static Object xml2map(Element element) {
        Map<String, Object> map = new HashMap<String, Object>();
        List<Element> elements = element.elements();
        if (elements.size() == 0) {
            map.put(element.getName(), element.getText());
            if (!element.isRootElement()) {
                return element.getText();
            }
        } else if (elements.size() == 1) {
            map.put(elements.get(0).getName(), xml2map(elements.get(0)));
        } else if (elements.size() > 1) {
            // 多个子节点的话就得考虑list的情况了，比如多个子节点有节点名称相同的
            // 构造一个map用来去重
            Map<String, Element> tempMap = new HashMap<String, Element>();
            for (Element ele : elements) {
                tempMap.put(ele.getName(), ele);
            }
            Set<String> keySet = tempMap.keySet();
            for (String string : keySet) {
                Namespace namespace = tempMap.get(string).getNamespace();
                List<Element> elements2 = element.elements(new QName(string, namespace));
                // 如果同名的数目大于1则表示要构建list
                if (elements2.size() > 1) {
                    List<Object> list = new ArrayList<Object>();
                    for (Element ele : elements2) {
                        list.add(xml2map(ele));
                    }
                    map.put(string, list);
                } else {
                    // 同名的数量不大于1则直接递归去
                    map.put(string, xml2map(elements2.get(0)));
                }
            }
        }

        return map;
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        String s = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <data><message> <status>0</status> <value>处理成功</value></message> <policeCheckInfos><policeCheckInfo name=\"刘静静\" id=\"110107197111011528\"> <message><status>0</status><value>查询成功</value></message><name desc=\"姓名\">刘静静</name><identitycard desc=\"身份证号\">110107197111011528</identitycard> <compStatus desc=\"比对状态\">2</compStatus><compResult desc=\"比对结果\">不一致</compResult></policeCheckInfo> </policeCheckInfos></data>";
        Map<String, String> m = XMLUtil.fromXmlString(s);
        System.out.println(m.toString());
        // Map<String, Object> m = Maps.newHashMap();
        // m.put("appId", "wx123435");
        // m.put("joined", new Date());
        //
        // System.out.println(XStreamUtil.toXML(m));
        // String json = XStreamUtil.toJson(m);
        // Map<String, Object> m2 = XStreamUtil.fromJson(json);
        //
        // String xml = XStreamUtil.toXML(m2);
        // Map<String, Object> m3 = XStreamUtil.fromXml(xml);
        //
        // System.out.println(m);
        // System.out.println(m2);
        // System.out.println(m3);

    }
}
